﻿using System.Text;

namespace RemoveCommentTool
{
    class RemoveComment
    {
        /**
        * 状态
        */
        enum State
        {
            CODE, // 正常代码
            SLASH, // 斜杠
            NOTE_MULTILINE, // 多行注释
            NOTE_MULTILINE_STAR, // 多行注释遇到*
            NOTE_SINGLELINE, // 单行注释
            BACKSLASH, // 折行注释
            CODE_CHAR, // 字符
            CHAR_ESCAPE_SEQUENCE, // 字符中的转义字符
            CODE_STRING, // 字符串
            STRING_ESCAPE_SEQUENCE// 字符串中的转义字符
        };

        /**
        * @function 删除代码中的注释，以string形式返回
        * @param inputFile 待删除注释的代码
        * @return 已删除注释的代码，string字符串形式
        */
        public string removeProgramComment(string inputFile)
        {
            State state = State.CODE;// Initiate
            StringBuilder stringBuilder = new StringBuilder();

            for (int i = 0; i < inputFile.Length; ++i)
            {
                char c = inputFile[i];
                switch (state)
                {
                    case State.CODE:
                        if (c == '/')
                        {
                            state = State.SLASH;
                        }
                        else
                        {
                            stringBuilder.Append(c);
                            if (c == '\'')
                            {
                                state = State.CODE_CHAR;
                            }
                            else if (c == '\"')
                            {
                                state = State.CODE_STRING;
                            }
                        }
                        break;
                    case State.SLASH:
                        if (c == '*')
                        {
                            state = State.NOTE_MULTILINE;
                        }
                        else if (c == '/')
                        {
                            state = State.NOTE_SINGLELINE;
                        }
                        else
                        {
                            stringBuilder.Append('/');
                            stringBuilder.Append(c);
                            state = State.CODE;
                        }
                        break;
                    case State.NOTE_MULTILINE:
                        if (c == '*')
                        {
                            state = State.NOTE_MULTILINE_STAR;
                        }
                        else
                        {
                            if (c == '\n')
                            {
                                stringBuilder.Append("\r\n");//保留空行，当然，也可以去掉
                            }
                            state = State.NOTE_MULTILINE;//保持当前状态
                        }
                        break;
                    case State.NOTE_MULTILINE_STAR:
                        if (c == '/')
                        {
                            state = State.CODE;
                        }
                        else if (c == '*')
                        {
                            state = State.NOTE_MULTILINE_STAR;//保持当前状态
                        }
                        else
                        {
                            state = State.NOTE_MULTILINE;
                        }
                        break;
                    case State.NOTE_SINGLELINE:
                        if (c == '\\')
                        {
                            state = State.BACKSLASH;
                        }
                        else if (c == '\n')
                        {
                            stringBuilder.Append("\r\n");
                            state = State.CODE;
                        }
                        else
                        {
                            state = State.NOTE_SINGLELINE;//保持当前状态
                        }
                        break;
                    case State.BACKSLASH:
                        if (c == '\\' || c == '\r' || c == '\n')
                        {//windows系统换行符为\r\n
                            if (c == '\n')
                            {
                                stringBuilder.Append("\r\n");//保留空行，当然，也可以去掉
                            }
                            state = State.BACKSLASH;//保持当前状态
                        }
                        else
                        {
                            state = State.NOTE_SINGLELINE;
                        }
                        break;
                    case State.CODE_CHAR:
                        stringBuilder.Append(c);
                        if (c == '\\')
                        {
                            state = State.CHAR_ESCAPE_SEQUENCE;
                        }
                        else if (c == '\'')
                        {
                            state = State.CODE;
                        }
                        else
                        {
                            state = State.CODE_CHAR;//保持当前状态
                        }
                        break;
                    case State.CHAR_ESCAPE_SEQUENCE:
                        stringBuilder.Append(c);
                        state = State.CODE_CHAR;
                        break;
                    case State.CODE_STRING:
                        stringBuilder.Append(c);
                        if (c == '\\')
                        {
                            state = State.STRING_ESCAPE_SEQUENCE;
                        }
                        else if (c == '\"')
                        {
                            state = State.CODE;
                        }
                        else
                        {
                            state = State.CODE_STRING;//保持当前状态
                        }
                        break;
                    case State.STRING_ESCAPE_SEQUENCE:
                        stringBuilder.Append(c);
                        state = State.CODE_STRING;
                        break;
                    default:
                        break;
                }
            }
            return stringBuilder.ToString();
        }
    }
}
